package com.wxxymaker.controller;

import com.blade.kit.Base64;
import com.wxxymaker.model.entity.*;
import com.wxxymaker.service.*;
import com.wxxymaker.utils.*;
import com.wxxymaker.utils.auth.AuthUtil;
import com.wxxymaker.utils.web.ResponseWarp;
import com.wxxymaker.utils.web.ShopUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.*;
import java.util.function.Function;

/**
 * @Author: Soft
 * @Date: 2018/5/5 0:49
 * @Desc: 后台管理控制器
 */
@Controller
@RequestMapping("/admin")
public class AdminHandler implements BaseHandler<Admin> {
    private final static Logger log = LoggerFactory.getLogger(AdminHandler.class);

    @Autowired
    private AdminService adminService;

    @Autowired
    private UserService userService;

    @Autowired
    private ShopService shopService;

    @Autowired
    private MarkService markService;

    @Autowired
    private StageService stageService;

    @Autowired
    private StageCountService stageCountService;

    @Autowired
    private MarkRecordService markRecordService;

    @Autowired
    private DeletedShopService deletedShopService;

    @Autowired
    private DeletedStageCountService deletedStageCountService;

    /**
     * 用户登录
     * @param admin    要登录的用户
     * @param session  页面session
     * @param response 响应
     */
    @PostMapping("/login")
    @ResponseBody
    public ResponseWarp login(Admin admin,  HttpSession session,
                              HttpServletResponse response) {
        if (adminService.checkAdmin(admin)) {
            String base64Md5 = AuthUtil.toBase64Md5(admin);
            if ("true".equals(admin.getRemember())) {
                Cookie cookie = new Cookie(Const.A_COOKIE, base64Md5);
                cookie.setMaxAge(7*24*3600);
                response.addCookie(cookie);
            }
            session.setAttribute(Const.A_SESSION, base64Md5);
            return ResponseWarp.ok("登录成功！");
        }
        return ResponseWarp.error("账号密码信息错误！");
    }

    /**
     * 用户注销登录
     */
    @PostMapping("/logout")
    @ResponseBody
    public ResponseWarp logout(HttpSession session,
                               HttpServletResponse response) {
        Cookie cookie = new Cookie(Const.A_COOKIE, "");
        cookie.setMaxAge(0);
        session.removeAttribute(Const.A_SESSION);
        session.removeAttribute("admin"); // 权宜
        response.addCookie(cookie);
        return ResponseWarp.ok("注销成功！");
    }

    /**
     * 验证用户名是否占用
     * @param username 需要验证的用户名
     */
    @PostMapping("/check_username")
    @ResponseBody
    public ResponseWarp checkUsername(@RequestParam String username) {
        if (adminService.getByUsername(username) == null) {
            return ResponseWarp.ok("用户名未被占用，合法！");
        }
        return ResponseWarp.error("用户名已被占用，请替换！");
    }

    /**
     * 添加普通管理员
     * @param admin 管理员信息
     */
    @Override
    @PostMapping("/add")
    @ResponseBody
    public ResponseWarp add(Admin admin) {
        admin.setGrade(Admin.gradeDim.COMMON);
        Admin add = adminService.add(admin);
        if (null != add) {
            return ResponseWarp.ok("添加成功！");
        }
        return ResponseWarp.error("添加失败！");
    }

    /**
     * 删除普通管理员
     * @param id  要删除的记录id
     */
    @Override
    @PostMapping("/delete/{id}")
    @ResponseBody
    public ResponseWarp delete(@PathVariable Integer id) {
        Admin admin = adminService.delete(id);
        if (admin != null) {
            if (admin.getGrade() == Admin.gradeDim.COMMON) {
                return ResponseWarp.ok("删除成功！");
            }
            return ResponseWarp.error("超级管理无法删除！");
        }
        return ResponseWarp.error("删除失败！");
    }

    /**
     * 管理员信息修改
     * @param admin 要修改的管理信息
     */
    @Override
    @PostMapping("/change")
    @ResponseBody
    public ResponseWarp change(Admin admin) {
        boolean change = adminService.change(admin);
        if (change) {
            return ResponseWarp.ok("修改成功！");
        }
        return ResponseWarp.error("修改失败！");
    }

    /**
     * 根据id查询管理信息
     * @param id  要查询的记录id
     */
    @Override
    @PostMapping("/get/{id}")
    @ResponseBody
    public ResponseWarp get(@PathVariable Integer id) {
        Admin one = adminService.getOne(id);
        return ResponseWarp.ok(one);
    }

    /**
     * 管理员登录界面
     */
    @GetMapping("/login")
    public String login_(@RequestParam(defaultValue = "") String prev, ModelMap map) {
        map.put("prev", new String(Base64.decode(prev, Base64.NO_WRAP)));
        return this.render("login");
    }

    // 管理员主页
    @GetMapping({"", "/admin"})
    public String admin(ModelMap map) {
        Shop bestWy = shopService.getBest(Shop.TypeDim.WUYE);
        Shop bestSt = shopService.getBest(Shop.TypeDim.STUST);
        long count = userService.count();

        map.put("CanReg", SimpleCache.get(Const.ALLOW_USER));
        map.put("bestWy", bestWy);
        map.put("bestSt", bestSt);
        map.put("userNum", count);
        return render("admin");
    }

    /**
     * 打分控制界面
     * 传出二维码 阶段 所有公司 被打分公司信息
     */
    @GetMapping("/mark")
    public String mark(ModelMap map, HttpServletRequest request) {
        QRCodeUtil.QRCode qrCode = null;
        Stage             stage  = markService.getStage();
        Mark              mark   = markService.getMark();
        // 平台下所有公司
        List<Shop> shops = shopService.findAll(new Sort(Sort.Direction.ASC, "type"));
        if (mark.getCan()) {
            qrCode = QRCodeUtil.get(request, stage.getId(), null);
        }

        // 当前二维码可被打分的公司 id
        Integer[] targetIds = {};
        try {
            assert qrCode != null;
            String url = qrCode.getCode();
            String hex = url.substring(url.indexOf("ids=") + 4);
            targetIds = ArrayUtils.fromHexString(hex);
        } catch (Exception e) {
            log.error("qrCode不存在！");
        }

        // 当前阶段可被打分的公司
        List<Shop> targetShop = new LinkedList<>();
        if (stage.getId() != null &&  stage.getId() > 0) {
            List<Integer> ids = Arrays.asList(ShopUtil.getShopIdsArr(stage.getShopIds()));
            shops.forEach((shop)->{
                if (ids.contains(shop.getId())) {
                    targetShop.add(shop);
                }
            });
        }

        map.put("qr", qrCode);
        map.put("stage", stage);
        map.put("mark", mark);
        map.put("shops", shops);
        map.put("target", targetShop);
        map.put("targetIds", targetIds);
        return render("mark");
    }

    // 被打分项管理界面
    @GetMapping("/shops")
    public String shop(ModelMap map, @RequestParam(defaultValue = "1") Integer pageNo,
                       @RequestParam(defaultValue = "0") Integer type) {
        Page<Shop> page = null;
        if (type == 0) {
            page = shopService.page(pageNo, Const.pageSize);
        } else {
            page = shopService.page(pageNo, Const.pageSize, type);
        }
        map.put("pages", page);
        map.put("type", type);
        map.put("shopTypeMap", Const.shopTypeMap);
        return render("shops");
    }

    // 打分阶段管理界面
    @GetMapping("/stage")
    public String stage(ModelMap map, @RequestParam(defaultValue = "1") Integer pageNo) {
        Mark mark = markService.getMark();
        Integer stageId = 0;
        if (mark.getStage() != null) {
            stageId = mark.getStage().getId();
        }
        Page<Stage> page = stageService.page(pageNo, Const.pageSize);
        map.put("pages", page);
        map.put("stageId", stageId);
        return render("stage");
    }

    // 打分记录管理界面
    @GetMapping("/record")
    public String record(ModelMap map, @RequestParam Map<String, Object> maps) {
        Integer pageNo = 1;
        if (maps.containsKey("pageNo")){
            try {
                pageNo = Integer.parseInt(maps.remove("pageNo").toString());
            } catch (Exception e) {
                pageNo = 1;
            }
        }
        // 新增用来根据用户名搜索
        if (maps.containsKey("name")){
            String uName = (String) maps.remove("name");
            if (!"".equals(uName)) {
                List<Integer> userIds = new LinkedList<>();
                userIds.add(0);
                userService.getByLikeName(uName).forEach((user -> {
                    userIds.add(user.getId());
                }));
                maps.put("user_ids", userIds);
            }
            map.put("name", uName);
        }
        Page<Shop> shops = shopService.page(1, 10000);
        Page<Stage> stages = stageService.page(1, 10000);
        Page<MarkRecord> page = markRecordService.page(maps, pageNo);
        map.put("shops", shops);
        map.put("stages", stages);
        map.put("pages", page);
        maps.forEach(map::put);
        return render("record");
    }

    // 打分阶段记录界面
    @GetMapping("/count")
    public String count(ModelMap map, @RequestParam Map<String, Object> query) {
        int pageNo = 1;
        if (query.containsKey("pageNo")){
            try {
                pageNo = Integer.parseInt(query.remove("pageNo").toString());
            } catch (Exception e) {
                pageNo = 1;
            }
        }

        Page<Shop> shops = shopService.page(1, 10000);
        Page<Stage> stages = stageService.page(1, 10000);
        Page<StageCount> page = stageCountService.page(pageNo, Const.pageSize, query);
        map.put("shops", shops);
        map.put("stages", stages);
        map.put("pages", page);
        query.forEach(map::put);
        return render("count");
    }

    /**
     * 公司历史阶段记录
     * @param map 历史阶段记录值
     * @return 公司历史评分阶段信息
     */
    @GetMapping("/history")
    public String history(ModelMap map, @RequestParam Map<String, Object> query) {
        int pageNo = 1;
        if (query.containsKey("pageNo")){
            try {
                pageNo = Integer.parseInt(query.remove("pageNo").toString());
            } catch (Exception ignored) {
            }
        }

        List<DeletedShop> shops = deletedShopService.findAll();
        List<Map<String, Object>> stages = deletedStageCountService.findStageNames();
        Page<DeletedStageCount> page = deletedStageCountService.page(pageNo, Const.pageSize, query);
        map.put("shops", shops);
        map.put("stages", stages);
        map.put("pages", page);
        query.forEach(map::put);
        return render("history");
    }

    // 用户管理界面
    @GetMapping("/users")
    public String user(ModelMap map, @RequestParam(defaultValue = "1") Integer pageNo,
                       @RequestParam(defaultValue = "0") Integer post,
                       @RequestParam(defaultValue = "") String name) {
        Map<String, Object> maps = new HashMap<>();
        maps.put("post", post);
        String decode = name;
        try {
            decode = URLDecoder.decode(name, "gbk");
        } catch (Exception e) {
            decode = "";
        }
        maps.put("name", decode);
        Page<User> page = userService.page(pageNo, Const.pageSize, maps);
        map.put("pages", page);
        map.put("post", post); // 数据显示到前端，当进行分页查询时使用
        map.put("name", decode);
        return render("users");
    }

    // 系统设置界面
    @GetMapping("/setting")
    public String setting() {
        return render("setting");
    }

    // 系统分值设置界面
    @GetMapping("/scoresetting")
    public String scoresetting(ModelMap map) throws IOException {
        Map<String, Double> standardProp = FileUtil.getStandardProp();
        map.addAllAttributes(standardProp);

        return render("scoresetting");
    }

    // 管理员列表界面
    @GetMapping("/list")
    public String adminList(ModelMap map, @RequestParam(defaultValue = "") String name,
                            @RequestParam(defaultValue = "1") Integer pageNo) {
        Page<Admin> page = adminService.page(pageNo, Const.pageSize, 0, name);
        map.put("pages", page);
        map.put("name", name);
        return render("alist");
    }

    /**
     * 添加管理员页面
     */
    @GetMapping("/add")
    public String add_() {
        return render("admin-ac");
    }

    /**
     * 超级管理员修改普通管理员信息界面
     * @param id 被修改的管理员id
     */
    @GetMapping("/change/{id}")
    public String change_(ModelMap map, @PathVariable Integer id){
        Admin admin = adminService.getOne(id);
        map.put("change", admin);
        return render("admin-ac");
    }

    // 返回admin目录下的视图
    private String render(String page) {
        return "/admin/" + page;
    }
}
